package jsyf.com.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import jsyf.com.constant.Const;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;


/**
 * @author: @张晓满 @Tupurp
 * @creat: 2017/11/3 13:37
 * description: 高德地图服务工具类
 */
public class GaoDeMapUtils {
    private GaoDeMapUtils(){};

    /**高德web服务开发AK*/
    private static final String GAODE_APP_KEY = Const.GAODE_APP_KEY;


    /**
     * @param unicodeString unicode字符串
     * @Description: unicode转换为中文  <br/>
     * @return: java.lang.String
     * @author:  @张晓满 @Tupurp
     * @createTime: 2017/11/3 14:33
     * @Version: V1.0.0
     */
    private static String decodeUnicode(String unicodeString) {
        char aChar;
        int len = unicodeString.length();
        StringBuffer outBuffer = new StringBuffer(len);
        for (int x = 0; x < len;) {
            aChar = unicodeString.charAt(x++);
            if (aChar == '\\') {
                aChar = unicodeString.charAt(x++);
                if (aChar == 'u') {
                    int value = 0;
                    for (int i = 0; i < 4; i++) {
                        aChar = unicodeString.charAt(x++);
                        switch (aChar) {
                            case '0':
                            case '1':
                            case '2':
                            case '3':
                            case '4':
                            case '5':
                            case '6':
                            case '7':
                            case '8':
                            case '9':
                                value = (value << 4) + aChar - '0';
                                break;
                            case 'a':
                            case 'b':
                            case 'c':
                            case 'd':
                            case 'e':
                            case 'f':
                                value = (value << 4) + 10 + aChar - 'a';
                                break;
                            case 'A':
                            case 'B':
                            case 'C':
                            case 'D':
                            case 'E':
                            case 'F':
                                value = (value << 4) + 10 + aChar - 'A';
                                break;
                            default:
                                throw new IllegalArgumentException(
                                        "Malformed   \\uxxxx   encoding.");
                        }

                    }
                    outBuffer.append((char) value);
                } else {
                    if (aChar == 't') {
                        aChar = '\t';
                    }
                    else if (aChar == 'r') {
                        aChar = '\r';
                    }
                    else if (aChar == 'n') {
                        aChar = '\n';
                    }
                    else if (aChar == 'f') {
                        aChar = '\f';
                    }
                    outBuffer.append(aChar);
                }
            } else {
                outBuffer.append(aChar);
            }
        }
        return outBuffer.toString();

    }

    /**
     * @param address 要查询的详细地址
     * @param city 地址所在的城市名。用于指定上述地址所在的城市，当多个城市都有上述地址时，该参数起到过滤作用，但不限制坐标召回城市。
     * @Description: 调用高德地图的正地理编码，根据输入地址获得对应的经纬度坐标map集合,当无相关结果时返回为Null   <br/>
     * @return: java.util.Map<java.lang.String,java.lang.String> lng:经度 lat:纬度
     * @author:  @张晓满 @Tupurp
     * @createTime: 2017/11/3 15:25
     * @Version: V1.0.0
     */
    public static Map<String, String> getLatitude(String address,String city) {
        Map<String,String> map = new HashMap<>();
        try {
            /**将地址转换成utf-8的16进制*/
            address = URLEncoder.encode(address, "UTF-8");

            /**拼装请求*/
            URL resjson = new URL("http://restapi.amap.com/v3/geocode/geo?address="
                    + address +"&city=" +city+"&key=" + GAODE_APP_KEY);
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    resjson.openStream()));
            String res;
            StringBuffer sb = new StringBuffer("");
            while ((res = in.readLine()) != null) {
                sb.append(res.trim());
            }
            in.close();

            /**得到返回数据Json*/
            String str = sb.toString();
            System.out.println("return json:" + str);
            JSONObject convert = FastJsonConvert.convertJSONToObject(str, JSONObject.class);

            /**成功，返回经纬度,失败，返回Null*/
            if(Const.INT_ONE.equals(convert.getInteger("status"))){
                JSONArray result = convert.getJSONArray("geocodes");
                /**经纬度为空*/
                if(Const.INT_ZERO.equals(result.size())){
                   return null;
                }
                String location = result.getJSONObject(0).getString("location");
                map.put("lng",String.valueOf(location.split(",")[0]));
                map.put("lat",String.valueOf(location.split(",")[1]));
                return map;

            }else{
                return null;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param latitudeMap 封装了经纬度的map集合
     * @Description: 根据经纬度反查真实地址  <br/>
     * @return: com.alibaba.fastjson.JSONObject
     * @author: @张晓满 @Tupurp
     * @createTime: 2017/12/7 10:21
     * @Version: V1.0.0
     */
    public static JSONObject getAddressByLatitude(Map<String,String> latitudeMap){

        /**返回Json对象*/
        JSONObject returnJsonObj = new JSONObject();

        /**拼装经纬度参数*/
        String lngAndLat = latitudeMap.get("lng");
        lngAndLat += ",";
        lngAndLat += latitudeMap.get("lat");

        try {
            URL resjson = new URL("http://restapi.amap.com/v3/geocode/regeo?location="
                    + lngAndLat +"&output=json&key=" + GAODE_APP_KEY);
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    resjson.openStream()));
            String res;
            StringBuffer sb = new StringBuffer("");
            while ((res = in.readLine()) != null) {
                sb.append(res.trim());
            }
            in.close();
            String str = sb.toString();
            System.out.println("return json:" + str);
            JSONObject convert = FastJsonConvert.convertJSONToObject(str, JSONObject.class);

            /**成功*/
            if(Const.INT_ONE.equals(convert.getInteger("status"))){

                /**得到包含省市区的详细地址*/
                String  addressDetail = convert.getJSONObject("regeocode").getString("formatted_address");
                /**得到省*/
                String  province = convert.getJSONObject("regeocode").getJSONObject("addressComponent").getString("province");
                /**得到市*/
                String  city = convert.getJSONObject("regeocode").getJSONObject("addressComponent").getString("city");
                /**得到县区*/
                String  district = convert.getJSONObject("regeocode").getJSONObject("addressComponent").getString("district");

                returnJsonObj.put("addressDetail",addressDetail);
                returnJsonObj.put("province",province);
                returnJsonObj.put("city",city);
                returnJsonObj.put("district",district);
                return returnJsonObj;

            }else{
                return null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;

    }


    /**
     * @param ip 查询的ip
     * @Description: 查询Ip所在的城市，当ip为空时，返回请求ip的所在城市(仅支持国内Ip)  <br/>
     * @return: java.util.Map<java.lang.String,java.lang.String> map中键代表含义：province：省(如果在局域网 IP网段内,则返回“局域网”,非
     * 法IP以及国外IP则返回空),city:市
     * @author:  @张晓满 @Tupurp
     * @createTime: 2017/11/3 15:05
     * @Version: V1.0.0
     */
    public static Map<String,String> getCityByIp(String ip){

        Map<String,String> resultMap = new HashMap<>();


        try {
            /**封装请求参数*/
            URL resjson = new URL("http://restapi.amap.com/v3/ip?ip="+ip+"&key="+GAODE_APP_KEY);
            if(StringUtils.isBlank(ip)){
                 resjson = new URL("http://api.map.baidu.com/location/ip?&key="+GAODE_APP_KEY);
            }

            /**发送url请求*/
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    resjson.openStream()));
            String res;
            StringBuffer sb = new StringBuffer("");
            while ((res = in.readLine()) != null) {
                sb.append(res.trim());
            }
            in.close();

            /**将请求结果转换为Json*/
            String str = sb.toString();
            str=decodeUnicode(str);
            System.out.println("return json:" + str);
            JSONObject convert =FastJsonConvert.convertJSONToObject(str, JSONObject.class);

            /**状态值为0,失败*/
            if(convert.getInteger("status").equals(Const.INT_ZERO)){
                return null;
            }

            /**得到省和市*/
            resultMap.put("province",convert.getString("province"));
            resultMap.put("city",convert.getString("city"));
            return resultMap;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return  null;
    }


    public static void main(String args[]) {

      Map map = GaoDeMapUtils.getLatitude("城东区","西宁市");
      System.out.println(map.get("lng"));
      System.out.println(map.get("lat"));
      System.out.println("*****************************");
      JSONObject jsonObject = GaoDeMapUtils.getAddressByLatitude(map);

        System.out.println(jsonObject.getString("addressDetail"));
        System.out.println(jsonObject.getString("province"));
        System.out.println(jsonObject.getString("city"));
        System.out.println(jsonObject.getString("district"));


      System.out.println("*****************************");
      Map resultMap = getCityByIp("121.229.129.42");
      System.out.println(resultMap.toString());


    }
}
